package config

import (
	"gitee.com/dennis-kk/service-box-go/util/config/reader"
	"gitee.com/dennis-kk/service-box-go/util/config/source"
	"gitee.com/dennis-kk/service-box-go/util/config/source/apollo"
	"gitee.com/dennis-kk/service-box-go/util/config/source/file"
	"gitee.com/dennis-kk/service-box-go/util/config/source/memory"
	"strings"
)

// Config is an interface abstraction for dynamic configuration
type Config interface {
	// Values provide the reader.Values interface
	reader.Values
	// Init the config
	Init(opts ...Option) error
	// Options in the config
	Options() *Options
	// Close Stop the config loader
	Close() error
	// Load config sources
	Load(source ...source.Source) error
}

var (
	//DefaultConfig Default Config Manager
	DefaultConfig Config
)

// NewConfig returns new config
func NewConfig(opts ...Option) (Config, error) {
	return newConfig(opts...)
}

// Load config sources
func Load(source ...source.Source) error {
	return DefaultConfig.Load(source...)
}

// LoadFile is short hand for creating a file source and loading it
func LoadFile(path string) (Config, error) {
	cfg, err := newConfig()
	if err != nil {
		return nil, err
	}

	err = cfg.Load(file.NewSource(
		file.WithPath(path),
	))

	if err != nil {
		return nil, err
	}
	return cfg, nil
}

func LoadYaml(cfgStr string) (Config, error) {
	cfg, err := newConfig()
	if err != nil {
		return nil, err
	}

	err = cfg.Load(memory.NewSource(
		memory.WithYaml([]byte(cfgStr)),
	))

	return cfg, err
}

func LoadApollo(apolloCfg *apollo.Config) (Config, error) {
	cfg, err := newConfig()
	if err != nil {
		return nil, err
	}

	// 传入配置需要分割name space
	spaces := strings.Split(apolloCfg.NameSpace, ",")
	var sources []source.Source
	for _, space := range spaces {
		cfg := &apollo.Config{
			Host:      apolloCfg.Host,
			AppId:     apolloCfg.AppId,
			NameSpace: space,
			Cluster:   apolloCfg.Cluster,
			Secret:    apolloCfg.Secret,
			Timeout:   apolloCfg.Timeout,
			IsRetry:   apolloCfg.IsRetry,
			Auth:      apolloCfg.Auth,
			ConfigExt: apolloCfg.ConfigExt,
		}
		sources = append(sources, apollo.NewSource(
			apollo.WithApolloHost(cfg),
		))
	}

	err = cfg.Load(sources...)

	return cfg, err
}
